package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.RedisConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author ghy
 * @version 1.0.1
 * @date 2023-04-20 12:14:55
 */
@Service
@Slf4j
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 删除缓存
     * @param pattern
     */
    private void cleanDishCache(String pattern) {
        try{
            Set keys = redisTemplate.keys(pattern);
            redisTemplate.delete(keys);
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("从缓存中删除菜品时出问题了：{}", e.getMessage());
        }
    }

    /**
     * 条件查询菜品和口味
     * @param dish
     * @return
     */
    @Override
    public List<DishVO> listWithFlavor(Dish dish) {

        // 1.查询缓存   key = front::dish::cid_16
        String redisKey = RedisConstant.C_DISH_CID_PRE + dish.getCategoryId();
        List<DishVO> dishVOList = (List<DishVO>) redisTemplate.opsForValue().get(redisKey);
        // 2.有，直接返回
        if(dishVOList != null && dishVOList.size() > 0) {
            log.warn("从缓存中获取对应分类下的菜品数据--->11111" );
            return dishVOList;
        }
        // 3.没有，查询数据库，放入缓存
        //查询的是起售状态的菜品
        dish.setStatus(StatusConstant.ENABLE);
        List<Dish> dishList = dishMapper.list(dish);

        // map 就是基于集合中的原数据 转化成 新数据
        dishVOList = dishList.stream().map(item -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(item, dishVO);
            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = dishFlavorMapper.getByDishId(item.getId());
            dishVO.setFlavors(flavors);
            return dishVO;
        }).collect(Collectors.toList());
        //放入缓存，有效期为一个小时
        redisTemplate.opsForValue().set(redisKey, dishVOList, RedisConstant.C_DISH_CID_EXP, TimeUnit.MINUTES);
        log.warn("从数据库中获取对应分类下的菜品数据，并放入到缓存--->2222");
        return dishVOList;
    }


    @Override
    public Result<List<Dish>> list(Long categoryId) {
        Dish dish = Dish.builder()
                .categoryId(categoryId)
                .status(StatusConstant.ENABLE)
                .build();
        List<Dish> dishList = dishMapper.list(dish);
        return Result.success(dishList);
    }

    @Override
    @Transactional
    public Result update(DishDTO dishDTO) {

        //原分类在哪？  要获取修改前的原分类ID
        Long oldCid = dishMapper.getById(dishDTO.getId()).getCategoryId();

        // 1. 修改菜品基本数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dishMapper.update(dish);
        // 2. 删除原先菜品与口味关系
        dishFlavorMapper.deleteByDishId(dishDTO.getId());
        // 3. 新增菜品与口味关系
        // 设置dishid
        List<DishFlavor> flavors = dishDTO.getFlavors();
        flavors.stream().forEach(item -> item.setDishId(dishDTO.getId()));
        dishFlavorMapper.batchInsert(flavors);

        //清空缓存    A的分类由1变成2   要删除两个分类的菜品缓存数据
        // A的分类由1变成1   要删除一个分类【原分类】的菜品缓存数据
        cleanDishCache(RedisConstant.C_DISH_CID_PRE + oldCid);
        if(!oldCid.equals(dishDTO.getCategoryId())) {
            //删除菜品的新分类
            cleanDishCache(RedisConstant.C_DISH_CID_PRE + dishDTO.getCategoryId());
        }
        return Result.success();
    }

    @Override
    public Result<DishVO> findById(Long id) {
        //1.查询菜品基本数据
        Dish dish = dishMapper.getById(id);
        //2.查询菜品关联的口味数据
        List<DishFlavor> dishFlavorList =  dishFlavorMapper.getByDishId(id);
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        dishVO.setFlavors(dishFlavorList);
        return Result.success(dishVO);
    }

    @Override
    @Transactional
    public Result deleteByIds(List<Long> ids) {
        // 1.判断菜品是否可以删除
        // 1.1 根据ID查询菜品
        List<Dish> dishList = dishMapper.getByIds(ids);
        long count = dishList.stream()
                //过滤 status=1 的数据
                .filter(item -> item.getStatus().equals(StatusConstant.ENABLE)).count();
        if(count > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
        }
        // 1.2 根据ID查询关联的套餐数量
        // select count(id) from setmeal_dish where dish_id in (....)
        count = setmealDishMapper.getByDishIds(ids);
        if(count > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        // 2.删除菜品
        dishMapper.deleteByIds(ids);
        // 3.删除菜品品味数据
        dishFlavorMapper.deleteByDishIds(ids);

        //清空缓存
        cleanDishCache(RedisConstant.C_DISH_CID_PRE + "*");

        return Result.success();
    }

    @Override
    public Result<PageResult> pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        Page<DishVO> page = dishMapper.getCondition(dishPageQueryDTO);
        PageResult pageResult = new PageResult(page.getTotal(), page.getResult());
        log.warn("{}", pageResult);
        return Result.success(pageResult);
    }

    @Override
    @Transactional
    public Result add(DishDTO dishDTO) {
        //保存菜品基本数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dishMapper.insert(dish);

        //有口味，保存口味数据   bug修复
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors != null && flavors.size() > 0) {
            flavors.stream().forEach(item -> item.setDishId(dish.getId()));
            log.warn("{}", flavors);
            //设置菜品ID
            dishFlavorMapper.batchInsert(flavors);
        }
        //清空缓存
        cleanDishCache(RedisConstant.C_DISH_CID_PRE + dishDTO.getCategoryId());

        return Result.success();
    }

    @Override
    public Result startOrStop(Integer status, Long id) {
        //菜品要停售，判断是否有关联的套餐
        if(StatusConstant.DISABLE.equals(status)) {
            long count = setmealDishMapper.getByDishId(id);
            if(count > 0) {
                throw new DeletionNotAllowedException("当前菜品正有关联的套餐处于起售状态，不能停售！");
            }
        }
        Dish dish = Dish.builder()
                .id(id)
                .status(status)
                .build();
        dishMapper.update(dish);
        return Result.success();
    }
}
